import 'dart:io';

import 'package:dio/dio.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:fstudy/src/common/log.dart';
import 'package:fstudy/src/config/app_config.dart';
import 'package:fstudy/src/config/config_reader.dart';
import 'package:fstudy/src/database/migration/versions.dart';
import 'package:path/path.dart';
import 'package:sqflite_common_ffi/sqflite_ffi.dart';
import 'package:sqflite_common_ffi_web/sqflite_ffi_web.dart';
import 'package:flutter/foundation.dart' show kIsWeb;

import '../data/models/setting.dart';

class Global {
  static const String dbFileName = 'main.db';

  // 配置
  static late AppConfig config;

  // 网络连接
  static late Dio api;

  // 数据库连接
  static late Database db;

  static Future<void> init() async {
    WidgetsFlutterBinding.ensureInitialized();

    await _initDb();

    await _initConfig();

    _initApi();
  }

  static Future<void> close() async {
    db.close();
    api.close();
  }

  static void _initApi() {
    api = Dio(
      BaseOptions(
        baseUrl: config.aiApiUrl,
        headers: {'Authorization': 'Bearer ${config.aiApiKey}'},
      ),
    );
  }

  static Future<void> _initDb() async {
    sqfliteFfiInit();
    if (kIsWeb) {
      databaseFactory = databaseFactoryFfiWeb;
    } else if (Platform.isWindows || Platform.isLinux) {
      databaseFactory = databaseFactoryFfi;
    }
    db = await openDatabase(
      join(await getDatabasesPath(), dbFileName),
      onCreate: (db, version) {
        Migration.migrate(db, version);
      },
      onUpgrade: (db, oldVersion, newVersion) {
        Migration.migrate(db, newVersion, oldVersion: oldVersion);
      },
      onDowngrade: (db, oldVersion, newVersion) {
        Migration.rollback(db, oldVersion, newVersion: newVersion);
      },
      version: 2,
    );
  }

  static Future<void> _initConfig() async {
    await dotenv.load();
    ConfigReader.initialize();
    config = ConfigReader.get<AppConfig>('_config');
    if (config.isDev()) {
      Log.debug = true;
    }

    List<Map> settings = await db.rawQuery(
      'SELECT val FROM settings WHERE name=? LIMIT 1',
      [Setting.sDeviceId],
    );
    if (settings.length == 1) {
      config.deviceId = settings[0]['val'];
    }

    settings = await db.rawQuery(
      'SELECT val FROM settings WHERE name=? LIMIT 1',
      [Setting.sConversationId],
    );
    if (settings.length == 1) {
      config.conversationId = settings[0]['val'];
    }
  }
}
